package process_manager

import (
	"fmt"
	"github.com/shirou/gopsutil/process"
	"os"
	"path/filepath"
	"syscall"
	"time"
	"unsafe"

	"GK-app/logger"
)

var (
	//consoleCount int
	// failCount    int
	//mu sync.Mutex // 保护 failCount 的同步更新
	//logFile     *os.File
	lastLogSize int64 // 记录日志文件的最后大小
)

// GetDirectoryPath 获取目录路径，用户可以选择使用默认路径或输入自定义路径
func GetDirectoryPath() string {
	fmt.Print("是否使用iNode的默认路径(C:\\Program Files (x86)\\iNode\\iNode Client)(y/n): ")
	var input string
	_, _ = fmt.Scanln(&input)

	if input == "y" || input == "" {
		return `C:\Program Files (x86)\iNode\iNode Client`
	}

	fmt.Print("请输入自定义路径(iNode Client.exe的当前路径): ")
	_, _ = fmt.Scanln(&input)
	return input
}

// GetProcessPath 获取 iNode Client.exe 的进程路径
func GetProcessPath(directoryPath string) (string, error) {
	processPath := filepath.Join(directoryPath, "iNode Client.exe")
	if _, err := os.Stat(processPath); os.IsNotExist(err) {
		return "", fmt.Errorf("指定路径下不存在可执行文件: %s", processPath)
	}
	return processPath, nil
}

/*
// 获取进程路径
func getProcessExe(pid uint32) (string, error) {
	handle, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_VM_READ, false, pid)
	if err != nil {
		return "", err
	}
	defer func(handle windows.Handle) {
		_ = windows.CloseHandle(handle)
	}(handle)

	var exePath [windows.MAX_PATH]uint16
	err = windows.GetModuleFileNameEx(handle, 0, &exePath[0], uint32(len(exePath)))
	if err != nil {
		return "", err
	}

	return windows.UTF16ToString(exePath[:]), nil
}
*/

// KillProcessesInDirectory 杀死指定目录下的所有进程
func KillProcessesInDirectory(directoryPath string) error {
	// 获取目录下的所有 .exe 文件
	exeFiles, err := filepath.Glob(filepath.Join(directoryPath, "*.exe"))
	if err != nil {
		return fmt.Errorf("无法获取目录中的可执行文件: %v", err)
	}

	// 获取当前所有进程
	processes, err := process.Processes()
	if err != nil {
		return fmt.Errorf("无法获取进程列表: %v", err)
	}

	for _, p := range processes {
		exePath, err := p.Exe()
		if err != nil {
			// 如果无法获取进程的可执行文件路径，则跳过此进程
			continue
		}

		// 检查进程是否属于指定目录中的可执行文件
		for _, exeFile := range exeFiles {
			if exePath == exeFile {
				// 尝试终止进程
				if err := p.Kill(); err != nil {
					logger.LogError(fmt.Sprintf("无法杀死进程: %s (PID: %d)", exePath, p.Pid), err)
				} else {
					fmt.Printf("%s - 已关闭进程: %s (PID: %d)\n", time.Now(), exePath, p.Pid)
				}
			}
		}
	}

	return nil
}

// StartProcess 启动指定路径的进程
func StartProcess(processPath string) error {
	verb := "runas" // 使用 "runas" 请求 UAC 提升权限
	verbPtr, _ := syscall.UTF16PtrFromString(verb)
	exePtr, _ := syscall.UTF16PtrFromString(processPath)
	var showCmd int32 = 1 // SW_SHOWNORMAL

	// 调用 ShellExecuteW 提升权限
	ret, _, err := syscall.NewLazyDLL("shell32.dll").NewProc("ShellExecuteW").Call(
		0,
		uintptr(unsafe.Pointer(verbPtr)),
		uintptr(unsafe.Pointer(exePtr)),
		0,
		0,
		uintptr(showCmd),
	)

	// 检查返回值
	if ret <= 32 {
		return fmt.Errorf("无法启动进程: %v", err)
	}

	fmt.Printf("%s - %s 已启动\n", time.Now(), processPath)
	return nil
}

// HasNewErrorLog 获取日志文件大小，以判断是否有新错误生成
func HasNewErrorLog(logFilePath string) (bool, error) {
	fileInfo, err := os.Stat(logFilePath)
	if err != nil {
		return false, fmt.Errorf("无法获取日志文件信息: %v", err)
	}
	newSize := fileInfo.Size()

	// 检查文件大小是否有变化
	if newSize > lastLogSize {
		lastLogSize = newSize
		return true, nil // 新日志生成
	}
	return false, nil // 没有新日志
}

// MonitorAndRestartProcessIfNeeded 监控日志文件，并根据新错误决定是否杀死和重启进程
func MonitorAndRestartProcessIfNeeded(logFilePath, directoryPath, processPath string) error {
	// 检查日志是否有新的错误
	hasNewLog, err := HasNewErrorLog(logFilePath)
	if err != nil {
		return fmt.Errorf("日志文件监控错误: %v", err)
	}

	if hasNewLog {
		fmt.Println("检测到新的错误日志，尝试执行恢复操作...")

		// 杀死进程并重启
		if err := KillProcessesInDirectory(directoryPath); err != nil {
			logger.LogError("无法杀死进程", err)
			return err
		}
		if err := StartProcess(processPath); err != nil {
			logger.LogError("无法启动进程", err)
			return err
		}

		// 等待 15 秒让进程稳定运行
		time.Sleep(15 * time.Second)
	}

	return nil
}

/*
// 监控日志文件并检查是否有新的错误
func monitorLogFile(logFilePath string, directoryPath string, processPath string) {
	for {
		mu.Lock()

		// 检查是否有新的错误日志
		hasNewLog, err := HasNewErrorLog(logFilePath)
		if err != nil {
			fmt.Printf("日志文件监控错误: %v\n", err)
			mu.Unlock()
			time.Sleep(2 * time.Second) // 遇到错误时稍等一会儿再试
			continue
		}

		if hasNewLog {
			fmt.Printf("%s - 检测到新的错误日志，尝试执行恢复操作...\n", time.Now())

			// 杀死进程并重启
			if err := KillProcessesInDirectory(directoryPath); err != nil {
				logger.LogError("无法杀死进程", err)
			}
			if err := StartProcess(processPath); err != nil {
				logger.LogError("无法启动进程", err)
			}

			// 等待 15 秒让进程稳定运行
			time.Sleep(15 * time.Second)
		}

		consoleCount++
		if consoleCount >= 1000 {
			clear.ClearScreen()
			consoleCount = 0
		}

		mu.Unlock()
		time.Sleep(2 * time.Second) // 每 2 秒检查一次
	}
}
*/
// NetworkManager 控制网络检测和进程管理
/*
func NetworkManager() {
	logFile, err := logger.InitLogFile()
	if err != nil {
		fmt.Println("无法创建日志文件:", err)
		return
	}
	defer logFile.Close()

	directoryPath := getDirectoryPath()
	processPath, err := getProcessPath(directoryPath)
	if err != nil {
		logger.LogError("获取进程路径出错", err)
		return
	}

	for {
		mu.Lock()
		if request.CheckNetwork() {
			fmt.Printf("%s - 网络连接正常，不需要执行程序。\n", time.Now())
			failCount = 0
		} else {
			failCount++
			fmt.Printf("%s - 检测到网络连接失败，尝试执行恢复操作...\n", time.Now())
			if failCount >= 5 {
				if err := killProcessesInDirectory(directoryPath); err != nil {
					logger.LogError("无法杀死进程", err)
				}
				if err := startProcess(processPath); err != nil {
					logger.LogError("无法启动进程", err)
				}
				time.Sleep(20 * time.Second) // 等待 20 秒再进行检查
				failCount = 0
			}
		}
		consoleCount++
		if consoleCount >= 1000 {
			clear.ClearScreen()
			consoleCount = 0
		}
		mu.Unlock()
		time.Sleep(2 * time.Second) // 等待 2 秒后再次检查
	}
}
*/

/*
func ProcessManager() {
	var err error

	// 初始化日志文件
	logFile, err = logger.InitLogFile()
	if err != nil {
		fmt.Println("无法创建日志文件:", err)
		return
	}
	defer func(logFile *os.File) {
		_ = logFile.Close()
	}(logFile)

	// 获取目录和进程路径
	directoryPath := GetDirectoryPath()
	processPath, err := GetProcessPath(directoryPath)
	if err != nil {
		logger.LogError("获取进程路径出错", err)
		return
	}

	// 监控日志文件中的错误
	monitorLogFile("error.log", directoryPath, processPath)
}*/
